<?php

namespace app\common\behavior;

use iocphp\Service;
use think\Request;
use think\Config;
use think\Loader;
use think\Route;

/**
 * 加强插件与前台扩展 By PGcao
 */
class Addons
{
    public function appInit()
    {
        // 初始化时将 addons.php 缓存移动runtime缓存目录下 By PGcao
        $extraAddonsFile = Service::getExtraAddonsFile();
        if (!is_file($extraAddonsFile)) {
            file_put_contents($extraAddonsFile, "<?php\n\n" . "return [];\n");
            Service::refresh();
            Config::set(pathinfo(basename($extraAddonsFile), PATHINFO_FILENAME), Service::getCacheData());
        }

        // 初始化时将 site.php 缓存移动runtime缓存目录下 By PGcao
        $extraSiteFile = \app\common\model\Config::getExtraSiteFile();
        if (!is_file($extraSiteFile)) {
            if(Route::getBind('controller') !== '\app\admin\command\Install'){// 修复移动site.php路径后导致无法全新安装问题 By PGcao 2024.12.9
                \app\common\model\Config::refreshFile(true);
                Config::set(pathinfo(basename($extraSiteFile), PATHINFO_FILENAME), \app\common\model\Config::getCacheData());
            }
        }
    }

    /**
     * 重写后台URL调度，以满足插件后端控制器独立于插件目录内 By PGcao
     * 需要结合 app\admin\controller\Plugins 控制器使用达到识别插件后端控制器
     */
    public function appDispatch(&$dispatch)
    {
        if (Route::getBind('module') != 'admin') {
            // 绑定到 index 模块 Add By PGcao
            list($firstElement) = explode('/', request()->pathinfo());
            if (Route::getBind('controller') == '\app\admin\command\Install')
                $firstElement = 'install';
            if (!Config::get('url_domain_deploy') && !in_array($firstElement, ['api', 'install']) && !Route::getBind('module')) {
                Route::bind(Config::get('default_module')); // 绑定到index模块 PGcao
                Config::set('url_html_suffix', ''); // 去掉前台URL伪静态后缀 PGcao
            }
            return;
        }

        $request = Request::instance();
        list($path) = self::parseUrlPath($request->path());
        if (!preg_match('/^[A-Za-z](\w)*$/', $path[0])) {
            return;
        }

        $app_root = ROOT_PATH . 'addons' . DS . strtolower($path[0]) . DS . 'admin' . DS . 'controller';

        if (is_dir($app_root)) {
            if (!empty($path[1]) && strtolower($path[1]) !== strtolower(Config::get('default_controller'))) {
                // 分割成数组
                $array = explode('.', $path[1]);
                // 将所有元素转换为小写
                $lowercaseArray = array_map('strtolower', $array);
                // 获取最后一个元素并转换首字母为大写
                $lastElement = end($lowercaseArray);
                $lastElement = ucfirst($lastElement);
                // 移除最后一个元素
                array_pop($lowercaseArray);
                // 将首字母大写的最后一个元素附加回数组
                $lowercaseArray[] = $lastElement;

                $file = implode(DS, $lowercaseArray);
                if (is_file($app_root . DS . $file . EXT)) {
                    $action = array_slice($path, 2, 1); // 取出第三个元素作为方法名
                    $action = !empty($action) ? array_shift($action) : Config::get('default_action');
                    $controller = strtolower(implode('.', array_slice($path, 0, 2)));
                    $request->controller(Loader::parseName($controller, 1))->action($action);
                    $controller = $request->controller();
                    !$dispatch && $dispatch = [
                        'type' => 'module',
                        'module' => [
                            'admin',
                            $controller,
                            $action
                        ]
                    ];
                }
            }
        }
    }

    /**
     * 解析URL的pathinfo参数和变量 By PGcao
     * @access private
     * @param string $url URL地址
     * @return array
     */
    private static function parseUrlPath($url)
    {
        // 分隔符替换 确保路由定义使用统一的分隔符
        $url = str_replace('|', '/', $url);
        $url = trim($url, '/');
        $var = [];
        if (false !== strpos($url, '?')) {
            // [模块/控制器/操作?]参数1=值1&参数2=值2...
            $info = parse_url($url);
            $path = explode('/', $info['path']);
            parse_str($info['query'], $var);
        } elseif (strpos($url, '/')) {
            // [模块/控制器/操作]
            $path = explode('/', $url);
        } else {
            $path = [$url];
        }
        return [$path, $var];
    }
}